package com.example.com.netty.listen;

import com.example.com.netty.NettyBase;
import com.example.com.netty.NettyConAddress;
import com.example.com.netty.handle.NettyTCPHandler;
import com.example.com.netty.handle.NettyUDPHandler;
import com.example.com.netty.message.MessageDecoder;
import com.example.com.netty.message.MessageEncoder;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;

/**
 * @author 杜豪波
 * @description: TODO
 * @date 2020/1/3 14:22
 */
public class NettyClientListen {
    private static final Logger logger = LoggerFactory.getLogger(NettyClientListen.class);
    // 全局连接
    private EventLoopGroup eventLoopGroup = null;
    // Netty4监听服务名称
    private String serviceName=null;
    public static Channel currentChannel=null;

    /**
     * @function 构造函数
     */
    public NettyClientListen(){
        super();
    }
    /**
     * @function 构造函数
     */
    public NettyClientListen(String serviceName){
        this.serviceName = serviceName;
    }

    /**
     * @function 关闭连接
     */
    private void clientStop() {
        // 关闭
        if(eventLoopGroup != null){
            eventLoopGroup.shutdownGracefully();
            eventLoopGroup = null;
        }
    }

    /**
     * 客户端重连方法
     */
    public static void reConnClient(NettyConAddress address) {
        if (NettyBase.REQ_UDP.equalsIgnoreCase(address.getConType())) {
            new NettyClientListen().initUDP(address.getAddress());
        }else if (NettyBase.REQ_TCP.equalsIgnoreCase(address.getConType())) {
            new NettyClientListen().initTCP(address.getAddress());
        }
    }

    /**
     * @function 初始化 TCP服务
     * @param serviceIsa 服务端地址与端口
     * @return boolean 判断连接是否建立
     */
    public void initTCP(InetSocketAddress serviceIsa) {
        try {
            clientStop();// 关闭
            eventLoopGroup = new NioEventLoopGroup();
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup);
            bootstrap.channel(NioSocketChannel.class);
            bootstrap.option(ChannelOption.TCP_NODELAY, true);

            bootstrap.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {

                    ChannelPipeline pipeline = ch.pipeline();
                    // 服务端设置的超时时间是30秒,客户端设置29秒
                    pipeline.addLast(new IdleStateHandler(0, 29, 0, TimeUnit.SECONDS));
                    pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
                    pipeline.addLast(new LengthFieldPrepender(4));
                    pipeline.addLast(new MessageDecoder(1<<20, 10, 4));
                    pipeline.addLast(new MessageEncoder());
                    // 客户端业务逻辑
                    pipeline.addLast("handler", new NettyTCPHandler());
                }
            });

            ChannelFuture channelFuture = bootstrap.connect(serviceIsa);
            currentChannel=channelFuture.channel();
            //添加客户端连接监听 重连操作在监听中进行处理
            channelFuture.addListener(null);
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @function 初始化 UDP服务
     * @param serviceIsa 服务端地址与端口
     * @return boolean 判断连接是否建立
     */
    public boolean initUDP(InetSocketAddress serviceIsa) {
        boolean backBool = false;
        try {
            clientStop();// 关闭
            eventLoopGroup = new NioEventLoopGroup();
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup);
            bootstrap.channel(NioDatagramChannel.class);
            bootstrap.handler(new NettyUDPHandler());

            ChannelFuture channelFuture = bootstrap.connect(serviceIsa).sync();
            // 休眠1秒
            TimeUnit.SECONDS.sleep(1L);
            // 是否连接成功
            backBool = channelFuture.isSuccess();
            logger.debug("开启客户端UDP,链接地址 " + serviceIsa.toString());
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("msg", e);
            backBool = false;
        }
        return backBool;
    }


}
